package com.wlyuan.open.interceptor;

import com.alibaba.fastjson.JSON;
import com.wlyuan.open.api.IOpenApiLogService;
import com.wlyuan.open.api.IOpenApiService;
import com.wlyuan.open.dto.api.OpenApiLogCreationDTO;
import com.wlyuan.open.utils.IpUtils;
import com.wlyuan.web.claim.Claim;
import com.wlyuan.web.claim.ClaimUtils;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.apache.dubbo.config.annotation.DubboReference;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

/**
 * @author lijing
 * @description 请求日志切面
 */
@Component
@Aspect
@Slf4j
public class LogAspect {
    @DubboReference(check = false)
    private IOpenApiLogService openApiLogService;
    @DubboReference(check = false)
    private IOpenApiService openApiService;

    @Pointcut("@annotation(com.wlyuan.open.annotation.OpenApi)")
    public void log() {

    }

    @Around("log()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        StopWatch watch = new StopWatch();
        watch.start();
        var parameters = Optional.ofNullable(pjp.getArgs()).orElse(new Object[]{});
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();

        String requestURI = request.getRequestURI();
        String ip = IpUtils.getRemoteAddress(request);
        String method = request.getMethod();

        Claim claim = ClaimUtils.get();
        Long tenantId = claim.getTenantId();
        Long userId = claim.getUserId();

        Object result = null;
        Long respTime = 0L;
        boolean success = true;
        Long apiId = null;
        try {
            /*//接口appId下该接口次数限制
            var openApiDetailVO = openApiService.getByUrlMethod(requestURI, method);
            if (openApiDetailVO == null) {
                result = "接口不存在";
                success = false;
                throw new ValueException("接口不存在");
            }
            apiId = openApiDetailVO.getApiId();*/
            //接口调用次数是否达到上限
            result = pjp.proceed();
            //减少总使用次数,增加成功调用次数
        } catch (Exception e) {
            result = e.getMessage();
            success = false;
            throw e;
        } finally {
            watch.stop();
            respTime = watch.getTotalTimeMillis();
            add(new OpenApiLogCreationDTO(requestURI, ip, tenantId, userId, JSON.toJSONString(parameters), getResult(result), success, respTime, apiId));
        }
        return result;
    }

    private void add(OpenApiLogCreationDTO creation) {
        openApiLogService.add(creation);
    }

    private static String getResult(Object obj) {
        if (obj == null) {
            return null;
        }
        try {
            return JSON.toJSONString(obj);
        } catch (Exception e) {
            return obj.toString();
        }
    }
}
